package org.ne.banksys.controller.admin;

import com.github.pagehelper.Page;
import com.opencsv.CSVWriter;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.ibatis.annotations.Param;
import org.ne.banksys.common.Result;
import org.ne.banksys.entity.Card;
import org.ne.banksys.entity.Deposit;
import org.ne.banksys.entity.Trade;
import org.ne.banksys.entity.User;
import org.ne.banksys.service.CardService;
import org.ne.banksys.service.DepositService;
import org.ne.banksys.service.TradeService;
import org.ne.banksys.service.UserService;
import org.ne.banksys.utils.CardIdCreateUtils;
import org.ne.banksys.utils.MD5Utils;
import org.ne.banksys.utils.ThreadLocalUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpHeaders;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.management.RuntimeErrorException;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author wey
 * @date 2025/6/16 上午10:19 06
 **/


@RestController
@RequestMapping("/admin")
public class AdminController {


    @Autowired
    private UserService userService;

    @Autowired
    private CardService cardService;

    @Autowired
    private TradeService tradeService;

    @Autowired
    private DepositService depositService;

    @GetMapping("/allUsers")
    public Result getUsersByPage(
            @RequestParam(defaultValue = "0") Integer page,
            @RequestParam(defaultValue = "10") Integer size
    ) {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }
        Page<User> userPage = userService.getAllUsers(page, size);
        return Result.success(userPage);
    }

    // 卡片分页查询
    @GetMapping("/allCards")
    public Result getCardsByPage(
            @RequestParam(defaultValue = "0") Integer page,
            @RequestParam(defaultValue = "10") Integer size
    ) {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }
        Page<Card> cardPage = cardService.getAllCards(page, size);
        return Result.success(cardPage);
    }

    // 交易记录分页查询
    @GetMapping("/allTrades")
    public Result getTradesByPage(
            @RequestParam(defaultValue = "0") Integer page,
            @RequestParam(defaultValue = "10") Integer size
    ) {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }
        Page<Trade> tradePage = tradeService.getAllTrades(page, size);
        return Result.success(tradePage);
    }




    @GetMapping("/usersCsv")
    public void exportUsersToCsv(HttpServletResponse response) throws IOException {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            throw new RuntimeException("非管理员");
        }
        // 1. 获取数据（排除password字段）
        List<User> users = userService.getAll();

        // 2. 设置响应头（解决中文乱码问题）
        response.setContentType("text/csv; charset=UTF-8");
        String fileName = "用户列表.csv";
        String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replace("+", "%20");
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
                "attachment; filename=\"" + encodedFileName + "\"");

        // 3. 使用OpenCSV写入响应流
        try (CSVWriter csvWriter = new CSVWriter(
                new OutputStreamWriter(response.getOutputStream(), "GBK"))) {

            // 表头保持不变
            csvWriter.writeNext(new String[]{"客户ID", "客户姓名", "身份证号", "地址", "电话"});

            for (User user : users) {
                String[] row = {
                        user.getCustomerId() != null ? user.getCustomerId().toString() : "",
                        user.getCustomerName(),
                        "\t" + user.getPID(),
                        user.getAddress() != null ? user.getAddress() : "",
                        user.getTelephone() != null ?"\t" + user.getTelephone() : ""
                };
                csvWriter.writeNext(row);
            }
        }
    }

    @GetMapping("/cardsCsv")
    public void exportCardsToCsv(HttpServletResponse response) throws IOException {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            throw new RuntimeException("非管理员");
        }
        // 1. 获取数据（排除password字段）
        List<Card> Cards = cardService .getAll();
        System.out.println(Cards);
        // 2. 设置响应头（解决中文乱码问题）
        response.setContentType("text/csv; charset=UTF-8");
        String fileName = "银行卡列表.csv";
        String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replace("+", "%20");
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
                "attachment; filename=\"" + encodedFileName + "\"");

        // 3. 使用OpenCSV写入响应流
        try (CSVWriter csvWriter = new CSVWriter(
                new OutputStreamWriter(response.getOutputStream(), "GBK"))) {

            // 表头保持不变
            csvWriter.writeNext(new String[]{"银行卡号", "客户姓名", "存款类型", "币种", "开户日期", "存款", "挂失"});

            for (Card card : Cards) {
                String[] row = {
                        card.getCardId() != null ? "\t" + card.getCardId() : "",
                        userService.findUserById( card.getCustomerId()).getCustomerName(),
                        depositService.getSavingName(card.getSavingId()),
                        card.getCurId(),
                        "\t"+card.getOpenDate().toString(),
                        card.getBalance().toString(),
                        card.getIsReportLoss()
                };
                csvWriter.writeNext(row);
            }
        }
    }

    @GetMapping("/tradesCsv")
    public void exportTradesToCsv(HttpServletResponse response) throws IOException {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            throw new RuntimeException("非管理员");
        }

        List<Trade> trades = tradeService.getAll();

        // 2. 设置响应头（解决中文乱码问题）
        response.setContentType("text/csv; charset=UTF-8");
        String fileName = "交易记录列表.csv";
        String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replace("+", "%20");
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
                "attachment; filename=\"" + encodedFileName + "\"");

        // 3. 使用OpenCSV写入响应流
        try (CSVWriter csvWriter = new CSVWriter(
                new OutputStreamWriter(response.getOutputStream(), "GBK"))) {

            // 表头保持不变
            csvWriter.writeNext(new String[]{"交易ID", "交易日期", "交易类型", "交易银行卡", "交易金额", "备注"});

            for (Trade trade : trades) {
                String[] row = {
                        trade.getTradeId() != null ? "\t" + trade.getTradeId() : "",
                        "\t"+trade.getTradeDate().toString(),
                        trade.getTradeType(),
                        "\t" + trade.getCardId(),
                        trade.getTradeMoney().toString(),
                        trade.getRemark()
                };
                csvWriter.writeNext(row);
            }
        }
    }

    //管理员删除用户
    @DeleteMapping("/deleteUser/{PID}")
    public Result deleteUserById(@PathVariable String PID) {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }

        User user = userService.findByUserPID(PID);
        if (user == null) {
            return Result.error("用户不存在");
        }
        userService.delete(user.getCustomerId());
        return Result.success();
    }



    //管理员删除信用卡
    @DeleteMapping("/deleteCard/{id}")
    public Result deleteCardById(@PathVariable String id) {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }
        Card card = cardService.selectCardById(id);
        if (card == null) {
            return Result.error("用户不存在");
        }
        cardService.deleteCard(id);
        return Result.success();
    }
    //管理员删除交易记录
    @DeleteMapping("/deleteTrade/{id}")
    public Result deleteTradeById(@PathVariable Long id) {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }
        Trade trade = tradeService.getById(id);
        if (trade == null) {
            return Result.error("用户不存在");
        }
        tradeService.delete(id);
        return Result.success();
    }


    //管理员修改用户

    @PostMapping("/updateUser")
    public Result updateUser(@RequestBody Map<String, Object> para) {

        if (para == null) {
            return Result.error("参数为空");
        }

        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }

        String PID = para.get("PID").toString();
        String customerName = para.get("customerName").toString();
        String telephone = para.get("telephone").toString();

        User user = userService.findByUserPID(PID);
        if (user == null) {
            return Result.error("用户不存在");
        }


        user.setCustomerName(customerName);
        user.setTelephone(telephone);


        user.setPID(PID);
        userService.update(user);

        return Result.success(userService.findByUserPID(PID));
    }


    //管理员修改银行卡\\
    @PostMapping("/updateCard")
    public Result updateCard(@RequestBody Map<String, Object> para) {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }

        String cardId = (String) para.get("cardId");
        String savingName = (String) para.get("savingName");
        String curId = (String) para.get("curId");
        String isReportLoss = (String) para.get("isReportLoss");


        Long savingId = depositService.getSavingId(savingName);
        Card card = cardService.selectCardById(cardId);
        if (card == null) {
            return Result.error("银行卡不存在");
        }

        card.setIsReportLoss(isReportLoss);
        card.setCurId(curId);
        card.setSavingId(savingId);
        cardService.update(card);

        return Result.success(cardService.selectCardById(cardId));

    }

    //管理员修改交易记录

    @PostMapping("/updateTrade")
    public Result updateTrade(@RequestBody Map<String, Object> para) {


        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }

        Long tradeId = Long.parseLong ((String) para.get("tradeId"));
        String remark = (String) para.get("remark");

        Trade trade = tradeService.getById(tradeId);

        trade.setRemark(remark);
        tradeService.update(trade);
        return Result.success(tradeService.getById(tradeId));
    }


    //管理员添加用户
    @PostMapping("/addUser")
    public Result addUser(@RequestBody Map<String, Object> para) {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }


        String customerName = (String) para.get("customerName");
        String telephone = (String) para.get("telephone");
        String PID = para.get("PID").toString();
        String password = (String) para.get("password");

        User user = userService.findByUserPID(PID);
        if (user != null) {
            return Result.error("用户已存在");
        }
        //userService.register(username, password, PID, phone);
        userService.register(customerName, password, PID, telephone);
        return Result.success(userService.findByUserPID(PID));
    }


    /* @Insert("insert into card(card_id,cur_id,saving_id,open_date,open_money,balance,pass,is_report_loss,customer_id)" +
            "values (#{cardId}, 'RMB', #{savingId}, #{openDate}, #{openMoney}, #{balance}, #{pass}, #{isReportLoss},#{customerId})")
    void add(Card card);*/
    //管理员添加银行卡
    @PostMapping("/addCard")
    public Result addCard(@RequestBody Map<String, Object> para) {

        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }

        String cardId = CardIdCreateUtils.createCardId();

        String savingName = (String) para.get("savingName");
        BigDecimal openMoney = new BigDecimal(para.get("openMoney").toString());
        String pass = (String) para.get("pass");
        Long customerId = Long.parseLong ((String) para.get("customerId"));

        Long savingId = depositService.getSavingId(savingName);
        Card card = cardService.selectCardById(cardId);
        if (card != null) {
            return Result.error("请重试");
        }
        Card newCard = new Card();
        newCard.setCardId(cardId);
        newCard.setSavingId(savingId);
        newCard.setPass(MD5Utils.code(pass));
        newCard.setCustomerId(customerId);
        newCard.setOpenMoney(openMoney);
        newCard.setBalance(openMoney);

        newCard.setOpenDate(new Timestamp(System.currentTimeMillis()));
        newCard.setIsReportLoss("否");
        cardService.insert(newCard);

        return Result.success(cardService.selectCardById(cardId));



    }

    /* @Insert("insert into trade(trade_date,trade_type,card_id,trade_money,remark)" +
            "values (#{tradeDate}, #{tradeType}, #{cardId}, #{tradeMoney}, #{remark})")
    void insert(Trade trade);*/


    //管理员添加交易记录
    @PostMapping("/addRecord")
    public Result addRecord(@RequestBody Map<String, Object> para) {

        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }

        String cardId = (String) para.get("cardId");
        String tradeType = (String) para.get("tradeType");
        Timestamp tradeDate = new Timestamp(System.currentTimeMillis());
        BigDecimal tradeMoney = new BigDecimal(para.get("tradeMoney").toString());
        String remark = (String) para.get("remark");


        Trade trade = new Trade();
        trade.setCardId(cardId);
        trade.setTradeType(tradeType);
        trade.setTradeDate(tradeDate);
        trade.setTradeMoney(tradeMoney);
        trade.setRemark(remark);
        tradeService.add(trade);

        return Result.success();

    }

    private Long DateToLong(String date) throws ParseException {
        Date parse = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(date);
        return parse.getTime();
    }

    @PostMapping("/searchCardByDate")
    public Result searchCardByDate(@RequestBody Map<String, Object> para) throws ParseException {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }
        String startDate = (String) para.get("startDate");
        String endDate = (String) para.get("endDate");


        Long timstamp1 = DateToLong(startDate);

        Long timstamp2 = DateToLong(endDate);

        Timestamp timestamp_start = new Timestamp(timstamp1);
        Timestamp timestamp_end = new Timestamp(timstamp2);
        List<Card> cards = cardService.filterByOpenDateRange(timestamp_start, timestamp_end);
        return Result.success(cards);

    }
    @PostMapping("/searchCardByMoney")
    public Result searchCardByMoney(@RequestBody Map<String, Object> para) {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }
        BigDecimal minMoney = new BigDecimal(para.get("minMoney").toString());
        BigDecimal maxMoney = new BigDecimal(para.get("maxMoney").toString());
        List<Card> cards = cardService.filterByOpenMoneyRange(minMoney, maxMoney);
        return Result.success(cards);
    }
    @PostMapping("/searchCardByBoth")
    public Result searchCardByBoth(@RequestBody Map<String, Object> para) throws ParseException{
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }
        BigDecimal minMoney = new BigDecimal(para.get("minMoney").toString());
        BigDecimal maxMoney = new BigDecimal(para.get("maxMoney").toString());
        String startDate = (String) para.get("startDate");
        String endDate = (String) para.get("endDate");
        Long timstamp1 = DateToLong(startDate);

        Long timstamp2 = DateToLong(endDate);

        Timestamp timestamp_start = new Timestamp(timstamp1);
        Timestamp timestamp_end = new Timestamp(timstamp2);
        List<Card> cards = cardService.filterCards(timestamp_start, timestamp_end, minMoney, maxMoney);
        return Result.success(cards);
    }


    @PostMapping("/searchTradeByDate")
    public Result searchTradeByDate(@RequestBody Map<String, Object> para) throws ParseException {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }

        String startDate = (String) para.get("startDate");
        String endDate = (String) para.get("endDate");
        Long timstamp1 = DateToLong(startDate);

        Long timstamp2 = DateToLong(endDate);

        Timestamp timestamp_start = new Timestamp(timstamp1);
        Timestamp timestamp_end = new Timestamp(timstamp2);
        List<Trade> trades = tradeService.filterByTradeDate(timestamp_start, timestamp_end);
        return Result.success(trades);


    }
    @PostMapping("/searchTradeByMoney")
    public Result searchTradeByMoney(@RequestBody Map<String, Object> para) throws ParseException {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }
        BigDecimal minMoney = new BigDecimal(para.get("minMoney").toString());
        BigDecimal maxMoney = new BigDecimal(para.get("maxMoney").toString());


        List<Trade> trades = tradeService.filterByTradeMoney(minMoney, maxMoney);
        return Result.success(trades);

    }
    @PostMapping("/searchTradeByBoth")
    public Result searchTradeByBoth(@RequestBody Map<String, Object> para) throws ParseException{
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }
        BigDecimal minMoney = new BigDecimal(para.get("minMoney").toString());
        BigDecimal maxMoney = new BigDecimal(para.get("maxMoney").toString());
        String startDate = (String) para.get("startDate");
        String endDate = (String) para.get("endDate");
        Long timstamp1 = DateToLong(startDate);

        Long timstamp2 = DateToLong(endDate);

        Timestamp timestamp_start = new Timestamp(timstamp1);
        Timestamp timestamp_end = new Timestamp(timstamp2);
        List<Trade> trades = tradeService.filterByDateAndMoney(minMoney, maxMoney, timestamp_start, timestamp_end);
        return Result.success(trades);


    }

    ///deposit  管理员部分

    @PostMapping("/addDeposit")
    public Result addDeposit(@RequestBody Map<String, Object> para){
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }

        String savingName = (String) para.get("savingName");
        String descrip = (String) para.get("descrip");

        Deposit d = depositService.getDeposit(savingName);
        if (d != null) {
            return Result.error("存款类别已经存在");
        }
        Deposit deposit = new Deposit();
        deposit.setDescrip(descrip);
        deposit.setSavingName(savingName);
        depositService.saveDeposit(deposit);
        return Result.success();
    }

    @GetMapping("/allDeposit")
    public Result allDeposit(){
        List<Deposit> res = depositService.getDeposits();
        return Result.success(res);
    }

    @PostMapping("/updateDeposit")
    public Result updateDeposit(@RequestBody Map<String, Object> para){
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }
        Long savingId = Long.parseLong( para.get("savingId").toString());
        String savingName = (String) para.get("savingName");
        String descrip = (String) para.get("descrip");

        if (depositService.getSavingName(savingId) == null) {
            return Result.error("该ID无效");
        }
        Deposit deposit = new Deposit();
        deposit.setSavingId(savingId);
        deposit.setDescrip(descrip);
        deposit.setSavingName(savingName);
        depositService.updateDeposit(deposit);
        return Result.success();
    }

    @DeleteMapping("/deleteDeposit")
    public Result deleteDeposit(@RequestBody Map<String, Object> para){
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }
        Long savingId = Long.parseLong( para.get("savingId").toString());
        depositService.deleteDeposit(savingId);
        return Result.success();
    }


    @GetMapping("/searchUser")
    public Result searchUser(@RequestParam String customerName) {
        Map<String, Object> info = ThreadLocalUtils.get();
        String adminName = info.get("customerName").toString();
        if (!"admin".equals(adminName)) {
            return Result.error("非管理员无法操作");
        }
        List<User> list = userService.searchUserByUserName(customerName);
        return Result.success(list);
    }



}
